﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using Microsoft.Xrm.Sdk.Messages;
using Xrm.Framework.Test.Integration;
using Xrm.Solutions.FrameworkSample.Common.Entities;


namespace Xrm.Solutions.FrameworkSample.XrmIntegrationTests.WFActivities
{
    [TestClass]
    public class TestManageAccountValue : AsyncIntegrationTest
    {
        #region Instance Variables

        private Account account;

        #endregion

        #region Properties

        protected override string AsyncOperationName
        {
            get
            {
                return "Manage Account Value";
            }
        }

        protected override int AsyncOperationType
        {
            get
            {
                return 10;
            }
        }

        #endregion

        #region Setup

        protected override OrganizationRequest SetupTriggerRequest()
        {
            CrmHelpers.SetConfigurationSetting(this.OrganizationService, "AutoNumberPrefix", "Test" + DateTime.Now);

            account = new Account();
            account.Name = "TestManageAccountValue " + DateTime.Now;
            account.Id = this.OrganizationService.Create(account);

            Opportunity opportunity1 = new Opportunity();
            opportunity1.Name = "TestManageAccountValue 1 " + DateTime.Now;
            opportunity1.ActualValue = new Money(1200000);
            opportunity1.ParentAccountId = account.ToEntityReference();

            CreateRequest trigger = new CreateRequest() { Target = opportunity1 };

            return trigger;
        }

        #endregion

        #region Test

        [TestMethod]
        public void RunTestManageAccountValue()
        {
            base.Test();
        }

        #endregion

        #region Verify

        protected override void VerifyStatus()
        {
            Assert.AreEqual(Status, AsyncStatus.Pass);

            //Verify Account Value
            decimal expectedTotal = 1200000;
            decimal actualTotal = RetrieveActualAccountValue();
            Assert.AreEqual(expectedTotal, actualTotal);

            //Verify email has been sent since Account is worth more than One Million
            IQueryable<Email> emails = AccountEmails(this.account);
            Assert.IsNotNull(emails);
            Assert.IsTrue(emails.ToList().Count > 0);
            
        }

        private IQueryable<Email> AccountEmails(Account account)
        {
            using (XrmServiceContext xrmContext = new XrmServiceContext(this.OrganizationService))
            {
                var emails = from email in xrmContext.EmailSet
                           where email.RegardingObjectId.Id == account.Id
                           select email;
                return emails;
            }
        }

        private decimal RetrieveActualAccountValue()
        {
            decimal actualTotal = 0M;

            using (XrmServiceContext xrmContext = new XrmServiceContext(this.OrganizationService))
            {
                var opps = from opp in xrmContext.OpportunitySet
                           where opp.AccountId.Id == account.Id
                           select opp.ActualValue;

                foreach (Money actual in opps)
                {
                    actualTotal += actual.Value;
                }
            }

            return actualTotal;
        }

        #endregion

        #region Clean up

        protected override void CleanUp()
        {
            base.CleanUp();

            using (XrmServiceContext xrmContext = new XrmServiceContext(this.OrganizationService))
            {
                var opps = from opp in xrmContext.OpportunitySet
                           where opp.AccountId.Id == account.Id
                           select opp.Id;

                foreach (Guid oppId in opps)
                {
                    this.OrganizationService.Delete("opportunity", oppId);
                }
            }

            this.OrganizationService.Delete(account.LogicalName, account.Id);

        }

        #endregion
    }
}
